﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using DevExpress.XtraEditors;
using LibraryMusicStore;
using DevExpress.XtraEditors.Controls;
using DevExpress.XtraEditors.DXErrorProvider;
using DevExpress.XtraGrid.Views.Base;

namespace AppMusicStore
{
    public partial class frmIssueEditor : DevExpress.XtraEditors.XtraForm
    {
        IRepository<IssueDetail> iDRepository;
        IRepository<Issue> issueRepository;
        IRepository<Receipt> receiptRepository;
        IRepository<Album> albumRepository;
        IRepository<VAT> vatRes;
        internal int? id;
        DataTable dt;
        string customer;

        public string Customer
        {
            get { return customer; }
            set { customer = value; }
        }

        public DataTable Dt
        {
            get { return dt; }
            set { dt = value; }
        }

        public IRepository<Issue> IssueRepository
        {
            get { return issueRepository; }
            set { issueRepository = value; }
        }

        public frmIssueEditor()
        {
            InitializeComponent();
        }

        private void frmAlbumEditor_Load(object sender, EventArgs e)
        {
            try
            {
                //txtCustomer hide
                
                //issueRepository = new Repository<Issue>();
                iDRepository = new Repository<IssueDetail>(issueRepository.GetContext());
                receiptRepository = new Repository<Receipt>(issueRepository.GetContext());
                albumRepository = new Repository<Album>(issueRepository.GetContext());
                vatRes = new Repository<VAT>(issueRepository.GetContext());

                RetriveData();

                if (id != null)
                {
                    lblId.Text = "Số phiếu: " + id;

                    var issue = issueRepository.GetById((int)id);
                        //Common.GetIssueById(id, db);
                    if (issue != null)
                    {
                        dateEdit1.EditValue = issue.IssueDate;
                        //lupUsername.EditValue = issue.Username;
                        txtCustomer.Text = issue.Username;

                        if (issue.IssueDetails.Count>0)
                            InitDataTable(issue);
                    }
                }
                else
                {
                    this.layoutId.HideToCustomization();
                    dateEdit1.EditValue = DateTime.Now;
                }

                btnCancel.CausesValidation = false;
            }
            catch (Exception)
            {
                this.Close();
                throw;
            }
        }

        private void RetriveData()
        {
            try
            {
                if (dt == null)
                    bindingSourceIssueDetail.DataSource = CreateDataTable();
                else
                {
                    txtCustomer.Text = customer;
                    bindingSourceIssueDetail.DataSource = dt;
                }
                bindingSourceTitle.DataSource = albumRepository.GetAll()
                    .Where(a => a.Deleted == null || a.Deleted == false)
                    .OrderByDescending(a => a.AlbumId);
            }
            catch (Exception)
            {
                throw;
            }
        }

        private void InitDataTable(Issue issue)
        {
            try
            {
                foreach (var item in issue.IssueDetails)
                {
                    DataRow row = dt.NewRow();

                    row["Title"] = item.AlbumId;
                    row["UnitPrice"] = item.UnitPrice;
                    row["Quantity"] = item.Quantity;
                    row["Price"] = item.UnitPrice * item.Quantity;
                    row["IssueDetailId"] = item.IssueDetailId;
                    dt.Rows.Add(row);
                }
                dt.AcceptChanges();
            }
            catch (Exception)
            {
                throw;
            }
        }

        private DataTable CreateDataTable()
        {
            dt = new DataTable("IssueDetail");
            dt.BeginInit();
            dt.Columns.Add("Title");
            dt.Columns.Add("UnitPrice", System.Type.GetType("System.Decimal"));
            dt.Columns.Add("Quantity", System.Type.GetType("System.Int32"));
            dt.Columns.Add("Price", System.Type.GetType("System.Decimal"));
            dt.Columns.Add("IssueDetailId", System.Type.GetType("System.Int32"));
            dt.EndInit();
            return dt;
        }

        #region "Button click"
        private void btnAccept_Click(object sender, EventArgs e)
        {
            try
            {
                //validate control
                this.ValidateChildren();
                for (int i = 0; i < gridView1.RowCount; i++)
                {
                    gridView1_ValidateRow(this.gridView1, 
                        new ValidateRowEventArgs(i, gridView1.GetDataRow(i)));
                }

                if (gridView1.HasColumnErrors) return;

                if (ErrorProvider1.HasErrors)
                {
                    foreach (var item in ErrorProvider1.GetControlsWithError())
                    {
                        item.Focus();
                        Common.ShowErrorBox(ErrorProvider1.GetError(item));
                        return;
                    }
                }

                if (gridView1.RowCount == 0)
                    if (Common.ShowQuestionBox("Chưa có album trong phiếu. Tiếp tục ?", "okcancel") ==
                        DialogResult.Cancel)
                        return;

                //check duplicate
                if (!CheckDuplicate())
                    return;

                //switch
                if (id != null)
                    Edit();
                else
                    Insert();
            }
            catch (Exception)
            {
                throw;
            }
        }

        private bool CheckDuplicate()
        {
            for (int i = 0; i < gridView1.RowCount - 1; i++)
            {
                for (int j = i + 1; j < gridView1.RowCount; j++)
                {
                    if (gridView1.GetDataRow(i)["Title"].ToString() ==
                        gridView1.GetDataRow(j)["Title"].ToString())
                    {
                        string str = "Trùng dữ liệu : " +
                            repositoryItemLookUpEdit1.GetDisplayText(gridView1.GetDataRow(i)["Title"]) +
                            " đã có.";

                        //if (Common.ShowQuestionBox(str, "okcancel") == DialogResult.OK)
                        //{
                        //    return true;
                        //    //i = gridView1.RowCount - 1;
                        //    //break;
                        //}
                        //else
                        //{
                        Common.ShowErrorBox(str);

                        gridView1.FocusedRowHandle = i;
                        return false;
                        //}
                    }
                }
            }
            return true;
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            try
            {
                if (id != null)
                {
                    DataTable dtChange = dt.GetChanges();
                    var issue = issueRepository.GetById((int)id);

                    if (dtChange != null 
                        || issue.Username != txtCustomer.Text.Trim()
                        || issue.IssueDate.Date != dateEdit1.DateTime.Date)
                    {
                        DialogResult rs = Common.ShowQuestionBox
                            ("Lưu thay đổi ? ", "yesnocancel");
                        if (rs == DialogResult.Yes)
                            btnAccept.PerformClick();
                        else if (rs == DialogResult.Cancel)
                            return;
                    }
                }
                else
                {
                    DialogResult rs = Common.ShowQuestionBox("Lưu phiếu ? ", "yesnocancel");
                    if (rs == DialogResult.Yes)
                        btnAccept.PerformClick();
                    else if (rs == DialogResult.Cancel)
                        return;
                }
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                this.Close();
            }
        }
        
        #endregion

        #region insert
        private void Insert()
        {
            try
            {
                var issue = new Issue();
                //create new object
                InitNewIssue(issue);

                //insert into database
                issueRepository.InsertOnSubmit(issue);
                issueRepository.SubmitChanges();

                //create Receipt details
                if (gridView1.RowCount>0)
                    CreateIssueDetails(issue);
            }
            catch (Exception)
            {
                //Common.ShowErrorBox(ex.Message);
                this.Close();
                throw;
            }

            Common.ShowInfomationBox("Thêm thành công.");

            this.DialogResult = DialogResult.OK;
        }

        private void InitNewIssue(Issue issue)
        {
            try
            {
                issue.IssueDate = Convert.ToDateTime(dateEdit1.EditValue);
                issue.Username = txtCustomer.Text.Trim();
                //issue.Username = lupUsername.EditValue.ToString();
                issue.Total = GetTotal();
            }
            catch (Exception)
            {
                throw;
            }
        }

        private decimal GetTotal()
        {
            try
            {
                return Convert.ToDecimal(gridView1.Columns["Price"].SummaryItem.SummaryValue);
            }
            catch (Exception)
            {
                throw;
            }
        }

        private void CreateIssueDetails(Issue issue)
        {
            IssueDetail issueDetail;
            for (int i = 0; i < gridView1.RowCount; i++)
            {
                var row = gridView1.GetDataRow(i);
                issueDetail = new IssueDetail();

                issueDetail.Quantity = Convert.ToInt32(row["Quantity"]);
                issueDetail.UnitPrice = Convert.ToDecimal(row["UnitPrice"]);
                issueDetail.Issue = issue;
                //issueDetail.AlbumId = Convert.ToInt32(row["Title"]);
                issueDetail.Album = albumRepository.GetById(Convert.ToInt32(row["Title"]));

                iDRepository.InsertOnSubmit(issueDetail);
                //db.IssueDetails.InsertOnSubmit(issueDetail);
            }
            iDRepository.SubmitChanges();
        }
        #endregion

        private void gridView1_InitNewRow(object sender, DevExpress.XtraGrid.Views.Grid.InitNewRowEventArgs e)
        {
	        DataRow row = gridView1.GetDataRow(e.RowHandle);
	        row["Quantity"] = 1;
            row["UnitPrice"] = 1;
        }

        private void gridView1_ValidateRow(object sender, DevExpress.XtraGrid.Views.Base.ValidateRowEventArgs e)
        {
            ColumnView view = (ColumnView)sender;
            var colTitle = view.Columns["Title"];
            var colQuantity = view.Columns["Quantity"];
            var colUnitPrice = view.Columns["UnitPrice"];

            //get value
            string title = view.GetRowCellValue(e.RowHandle, colTitle).ToString();

            //validity criterion
            if (title.Length == 0)
            {
                e.Valid = false;

                //set errors with specific descriptions for the columns
                view.SetColumnError(colTitle, "Chưa chọn album");
            }
            if (view.GetRowCellValue(e.RowHandle, colUnitPrice).ToString().Length == 0)
            {
                e.Valid = false;

                //set errors with specific descriptions for the columns
                view.SetColumnError(colUnitPrice, "Chưa nhập giá");
            }
            else if (Convert.ToDecimal(view.GetRowCellValue(e.RowHandle, colUnitPrice)) < (decimal)0.01)
            {
                e.Valid = false;

                //set errors with specific descriptions for the columns
                view.SetColumnError(colUnitPrice, "Giá phải lớn hơn 0");
            }

            var quantity = view.GetRowCellValue(e.RowHandle, colQuantity).ToString();
            
            if (quantity.Length == 0)
            {
                e.Valid = false;

                //set errors with specific descriptions for the columns
                view.SetColumnError(colQuantity, "Chưa nhập số lượng");
            }
            else if (Convert.ToInt32(quantity) < 1)
            {
                e.Valid = false;

                //set errors with specific descriptions for the columns
                view.SetColumnError(colQuantity, "Số lượng phải lớn hơn 0");
            }
            //if > 0 >> check stock
            else
            {
                int stock = GetStock();
                if (stock < Convert.ToInt32(quantity))
                {
                    e.Valid = false;
                    view.SetColumnError(colQuantity, "Tồn kho :" + stock);
                }
            }

            //if (gridView1.HasColumnErrors)
            //    return;

            ////tron du lieu trung

            //for (int i = 0; i < gridView1.RowCount; i++)
            //    if (i != e.RowHandle)
            //    {
            //        DataRow row = gridView1.GetDataRow(i);
            //        if (Convert.ToInt32(row["Title"]) == Convert.ToInt32(gridView1.GetRowCellValue(e.RowHandle, "Title")))
            //        {
            //            row["Quantity"] = Convert.ToInt32(row["Quantity"]) +
            //                Convert.ToInt32(gridView1.GetRowCellValue(e.RowHandle, "Quantity"));
            //            row["Price"] = Convert.ToInt32(row["Quantity"]) *
            //                Convert.ToDecimal(row["UnitPrice"]);
            //            gridView1.DeleteRow(e.RowHandle);
            //            gridControl1.Update();
            //            return;
            //        }
            //    }
        }

        private int GetStock()
        {
            try
            {
                int nhap = 0, xuat = 0;
                int albumId = Convert.ToInt32(gridView1.GetFocusedRowCellValue("Title"));
                
                foreach (var receipt in receiptRepository.GetAll())
                {
                    nhap += (from rd in receipt.ReceiptDetails
                             where rd.AlbumId == albumId
                             select rd.Quantity).Sum();
                }

                var issues = issueRepository.GetAll();

                if (id!=null)
                    issues = issues.Where(i => i.IssueId != id);

                foreach (var issue in issues)
                {
                    xuat += (from iD in issue.IssueDetails
                             where iD.AlbumId == albumId
                             select iD.Quantity).Sum();
                }

                return nhap - xuat;
            }
            catch (Exception ex)
            {
                Common.ShowErrorBox(ex.Message);
            }
            return 0;
        }

        private void repositoryItemLookUpEdit1_EditValueChanged(object sender, EventArgs e)
        {
            try
            {
                LookUpEdit lup = sender as LookUpEdit;

                var album = albumRepository.GetById(Convert.ToInt32(lup.EditValue));
                //Common.GetAlbumById(Convert.ToInt32(lup.EditValue), db);
                var unitPrice = album.Price * Common.GetVAT(vatRes.First().Value);
                var quantity = Convert.ToInt32(gridView1.GetFocusedRowCellValue("Quantity"));

                gridView1.SetFocusedRowCellValue("UnitPrice", unitPrice);
                gridView1.SetFocusedRowCellValue("Price", unitPrice * quantity);
            }
            catch (Exception)
            {
                throw;
                //Common.ShowErrorBox(ex.Message);
            }
        }

        private void repositoryItemCalcEditQuantity_EditValueChanged(object sender, EventArgs e)
        {
            try
            {
                CalcEdit calc = sender as CalcEdit;
                
                var unitPrice = gridView1.GetFocusedRowCellValue("UnitPrice");
                var quantity = Convert.ToInt32(calc.EditValue);

                if (unitPrice.ToString().Length == 0)
                    return;
                else if (quantity < 1 || Convert.ToDecimal(unitPrice) < 1)
                    return;

                gridView1.SetFocusedRowCellValue("Price", Convert.ToDecimal(unitPrice) * quantity);
            }
            catch (Exception)
            {
                throw;
                //Common.ShowErrorBox(ex.Message);
            }
        }

        private void repositoryItemCalcEditUnitPrice_EditValueChanged(object sender, EventArgs e)
        {
            try
            {
                CalcEdit calc = sender as CalcEdit;
                var unitPrice = Convert.ToDecimal(calc.EditValue);
                var quantity = gridView1.GetFocusedRowCellValue("Quantity");

                if (quantity.ToString().Length == 0)
                    return;
                else if (Convert.ToInt32(quantity) < 1 || unitPrice < 1)
                    return;

                gridView1.SetFocusedRowCellValue("Price", unitPrice * Convert.ToInt32(quantity));
            }
            catch (Exception)
            {
                throw;
                //Common.ShowErrorBox(ex.Message);
            }
        }

        private void repositoryItemBtnDelete_Click(object sender, EventArgs e)
        {
            gridView1.DeleteSelectedRows();
            gridControl1.Update();
        }

        #region edit
        private void Edit()
        {
            try
            {
                DataTable dtChange = dt.GetChanges();
                var issue = issueRepository.GetById((int)id);
                    //Common.GetIssueById(id, db);
                //if grid and provider have changed
                if (dtChange == null 
                    && issue.Username == txtCustomer.Text.Trim()
                    && issue.IssueDate.Date == dateEdit1.DateTime.Date)
                {
                    this.Close();
                    return;
                }

                DialogResult result = Common.ShowQuestionBox("Sửa phiếu xuất " + id + " ?", "okcancel");

                if (result == DialogResult.OK)
                {
                    InitNewIssue(issue);

                    issueRepository.SubmitChanges();
                    //db.SubmitChanges();

                    if (dtChange != null)
                    {
                        if (gridView1.RowCount > 0)
                            EditIssueDetails(issue, dtChange);
                        else if (gridView1.RowCount == 0) //delete all
                            DeleteAllIssueDetails(issue);
                    }

                    Common.ShowInfomationBox("Sửa thành công.");

                    this.DialogResult = DialogResult.OK;
                }

            }
            catch (Exception)
            {
                //Common.ShowErrorBox(ex.Message);
                this.Close();
                throw;
            }
        }

        private void EditIssueDetails(Issue issue, DataTable dtChange)
        {
            IssueDetail issueDetail;
            //row dont have receiptdetailid will insert, any else edit
            foreach (DataRow row in dtChange.Rows)
            {
                if (row.RowState == DataRowState.Deleted)
                {
                    int? issueDetailId =
                        Convert.ToInt32(row["IssueDetailId", DataRowVersion.Original]);

                    issueDetail = iDRepository.GetById((int)issueDetailId);
                        //Common.GetIssueDetailById(issueDetailId, db);
                    iDRepository.DeleteOnSubmit(issueDetail);
                    //db.IssueDetails.DeleteOnSubmit(issueDetail);
                }
                else if (row["IssueDetailId"].ToString()=="")
                {
                    issueDetail = new IssueDetail();

                    issueDetail.Quantity = Convert.ToInt32(row["Quantity"]);
                    issueDetail.UnitPrice = Convert.ToDecimal(row["UnitPrice"]);
                    issueDetail.Issue = issue;
                    //issueDetail.AlbumId = Convert.ToInt32(row["Title"]);
                    issueDetail.Album = albumRepository.GetById(Convert.ToInt32(row["Title"]));

                    iDRepository.InsertOnSubmit(issueDetail);
                    //db.IssueDetails.InsertOnSubmit(issueDetail);
                }
                else
                {
                    issueDetail = iDRepository.GetById(Convert.ToInt32(row["IssueDetailId"]));
                        //Common.GetIssueDetailById(id, db);

                    if (issueDetail == null)
                        continue;

                    issueDetail.Quantity = Convert.ToInt32(row["Quantity"]);
                    issueDetail.UnitPrice = Convert.ToDecimal(row["UnitPrice"]);
                    //issueDetail.AlbumId = Convert.ToInt32(row["Title"]);
                    issueDetail.Album = albumRepository.GetById(Convert.ToInt32(row["Title"]));

                }
            }

            iDRepository.SubmitChanges();
            //db.SubmitChanges();
        }

        private void DeleteAllIssueDetails(Issue issue)
        {
            iDRepository.DeleteAllOnSubmit(issue.IssueDetails);
            iDRepository.SubmitChanges();
        }
        #endregion

        private void AcceptToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.btnAccept.PerformClick();
        }

        private void CancelToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.btnCancel.PerformClick();
        }

        private void Check(object sender, CancelEventArgs e)
        {
            string str = null;

            //title required
            if (sender.GetType().Name == "DateEdit")
            {
                DateEdit de = (DateEdit)sender;
                if (de.Text.Trim().Length == 0)
                    str = "Chưa nhập ngày";
            }
            else if (sender.GetType() == typeof(TextEdit))
            {
                TextEdit txt = (TextEdit)sender;
                if (txt.Text.Trim().Length == 0)
                    str = "Chưa nhập khách hàng";
            }
            ErrorProvider1.SetIconAlignment((Control)sender, ErrorIconAlignment.MiddleRight);
            ErrorProvider1.SetError((Control)sender, str);
        }

        private void gridView1_ValidatingEditor(object sender, BaseContainerValidateEditorEventArgs e)
        {
            if (gridView1.FocusedColumn.Name == "colTitle")
            {
                //validity criterion
                if (e.Value.ToString() != "")
                {
                    gridView1.SetColumnError(gridView1.Columns["Title"], "");
                }
            }
            else if (gridView1.FocusedColumn.Name == "colQuantity")
            {
                if (Convert.ToInt32(e.Value) > 0)
                {
                    gridView1.SetColumnError(gridView1.Columns["Quantity"], "");
                }
            }
            else if (gridView1.FocusedColumn.Name == "colUnitPrice")
            {
                if (Convert.ToInt32(e.Value) > 0)
                {
                    gridView1.SetColumnError(gridView1.Columns["UnitPrice"], "");
                }
            }
        }

        private void gridView1_InvalidRowException(object sender, InvalidRowExceptionEventArgs e)
        {
            e.ExceptionMode = ExceptionMode.NoAction;
            if (gridView1.HasColumnErrors)
            {
                if (gridView1.GetColumnError(gridView1.Columns["Title"]) != "")
                    Common.ShowErrorBox(gridView1.GetColumnError(gridView1.Columns["Title"]));
                else if (gridView1.GetColumnError(gridView1.Columns["Quantity"]) != "")
                    Common.ShowErrorBox(gridView1.GetColumnError(gridView1.Columns["Quantity"]));
                else if (gridView1.GetColumnError(gridView1.Columns["UnitPrice"]) != "")
                    Common.ShowErrorBox(gridView1.GetColumnError(gridView1.Columns["UnitPrice"]));
            }
        }
    }
}